//package com.linb.pan.server.common.listener.file;
//
//import com.alibaba.fastjson.JSON;
//import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
//import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
//import com.baomidou.mybatisplus.core.toolkit.Wrappers;
//import com.linb.pan.server.common.event.file.FilePhysicalDeleteEvent;
//import com.linb.pan.server.common.event.log.ErrorLogEvent;
//import com.linb.pan.server.modules.file.entity.BPanFile;
//import com.linb.pan.server.modules.file.entity.BPanUserFile;
//import com.linb.pan.server.modules.file.enums.FolderFlagEnum;
//import com.linb.pan.server.modules.file.service.IFileService;
//import com.linb.pan.server.modules.file.service.IUserFileService;
//import com.linb.pan.storage.engine.core.StorageEngine;
//import com.linb.pan.storage.engine.core.context.DeleteFileContext;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.context.ApplicationContext;
//import org.springframework.context.ApplicationContextAware;
//import org.springframework.context.event.EventListener;
//import org.springframework.scheduling.annotation.Async;
//import org.springframework.stereotype.Component;
//
//import java.io.IOException;
//import java.util.List;
//import java.util.stream.Collectors;
//
//@Component
//@Slf4j
//public class FilePhysicalDeleteEventListener implements ApplicationContextAware {
//
//    @Autowired
//    private IFileService fileService;
//
//    @Autowired
//    private IUserFileService userFileService;
//
//    @Autowired
//    private StorageEngine storageEngine;
//
//    @Autowired
//    private ApplicationContext applicationContext;
//
//    public void setApplicationContext(ApplicationContext applicationContext) {
//        this.applicationContext = applicationContext;
//    }
//
//    @EventListener(classes = FilePhysicalDeleteEvent.class)
//    @Async(value = "eventListenerTaskExecutor")
//    public void physicalDeleteFile(FilePhysicalDeleteEvent event) {
//        log.info("事件监听-准备彻底删除:" + event.getAllRecords());
//        //1.查询无引用的实体文件记录
//        List<BPanUserFile> allRecords = event.getAllRecords();
//        if (CollectionUtils.isEmpty(allRecords)) {
//            return;
//        }
//        List<Long> realFileIdList = findAllUnusedRealFileIdList(allRecords);
//        List<BPanFile> realFileRecords = fileService.listByIds(realFileIdList);
//        if (CollectionUtils.isEmpty(realFileRecords)) {
//            return;
//        }
//        //2.删除记录
//        if (!fileService.removeByIds(realFileIdList)) {
//            ErrorLogEvent logEvent = new ErrorLogEvent(this,
//                    "文件实体记录: " + JSON.toJSONString(realFileIdList) + " 删除失败",
//                    0l);
//            applicationContext.publishEvent(logEvent);
//            return;
//        }
//        //3.物理删除
//        physicalDeleteFileByStorageEngine(realFileRecords);
//    }
//
//    /**
//     * 查询无引用的实体文件记录
//     */
//    private List<Long> findAllUnusedRealFileIdList(List<BPanUserFile> allRecords) {
//        List<Long> realFileIdList = allRecords.stream()
//                // 必须是文件而不是文件夹
//                .filter(r -> FolderFlagEnum.NO.getCode().equals(r.getFolderFlag()))
//                // 必须是未关联的
//                .filter(this::isUnused)
//                .map(BPanUserFile::getRealFileId)
//                .collect(Collectors.toList());
//        return realFileIdList;
//    }
//
//    /**
//     * 判断是否被引用
//     */
//    private boolean isUnused(BPanUserFile record) {
//        QueryWrapper<BPanUserFile> queryWrapper = Wrappers.query();
//        queryWrapper.eq("real_file_id", record.getRealFileId());
//        // 当b_pan_file有，但b_pan_user_file没有时，视为废弃
//        return userFileService.count(queryWrapper) == 0;
//    }
//
//    /**
//     * 物理删除
//     */
//    private void physicalDeleteFileByStorageEngine(List<BPanFile> realFileRecords) {
//        List<String> realPathList = realFileRecords.stream().map(BPanFile::getRealPath).collect(Collectors.toList());
//        DeleteFileContext context = new DeleteFileContext();
//        context.setRealFilePathList(realPathList);
//        try {
//            storageEngine.delete(context);
//        } catch (IOException e) {
//            ErrorLogEvent logEvent = new ErrorLogEvent(this,
//                    "实体文件idList: " + JSON.toJSONString(realPathList) + " 删除失败",
//                    0l);
//            applicationContext.publishEvent(logEvent);
//        }
//    }
//
//}
